package comments

import (
	"encoding/json"
	"errors"
	"financial_manual_server/util"
	"fmt"
	"log"
	"sort"
	"time"
)

// 评论结构
type CommentBody struct {
	Id         int              `json:"id"`         // 评论ID
	Pid        int              `json:"pid"`        // 回复的评论ID
	DocId      string           `json:"docId"`      //文档ID
	UserId     string           `json:"userId"`     // 评论人ID
	UserName   string           `json:"userName"`   // 评论人名称
	QuoteId    string           `json:"quoteId"`    // 引用人ID
	QuoteName  string           `json:"quoteName"`  // 引用人名称
	Content    string           `json:"content"`    // 评论内容
	CreateTime util.JsonTime    `json:"createTime"` // 创建时间
	AgreeCount int              `json:"agreeCount"` // 赞同数
	Replies    *CommentBodyList `json:"replies"`    // 树层结构，评论内容
}

type CommentBodyList []CommentBody

func (s CommentBodyList) Len() int {
	return len(s)
}

func (s CommentBodyList) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func (s CommentBodyList) Less(i, j int) bool {
	aCreateTime := time.Time(s[i].CreateTime)
	bCreateTime := time.Time(s[j].CreateTime)
	return aCreateTime.Before(bCreateTime) || s[i].Id < s[j].Id
}

// json转struct
func jsonUnmarshal(body []byte) (interface{}, error) {
	var result CommentBody
	log.Println("json -> struct", string(body))
	err := json.Unmarshal(body, &result)
	return result, err
}

// 查询所有评论
func listComment(docId string) (CommentBodyList, int) {
	// 查询有效的评论
	defaultSql := "SELECT ID, PID, DOC_ID, USER_ID, USER_NAME, QUOTE_ID, QUOTE_NAME, CONTENT, CREATE_TIME, AGREE_COUNT FROM COMMENTS WHERE DOC_ID = ? and DELETED = 0 ORDER BY CREATE_TIME"
	if db, err := getConn(); err == nil {
		rows, err := db.Query(defaultSql, docId)
		if err != nil {
			return CommentBodyList{}, 0
		}

		result := make(CommentBodyList, 0)
		m := make(map[int]CommentBody, 0)
		count := 0

		for rows.Next() {
			var item CommentBody
			var replies = make(CommentBodyList, 0)
			item.Replies = &replies
			_ = rows.Scan(&item.Id, &item.Pid, &item.DocId, &item.UserId, &item.UserName, &item.QuoteId, &item.QuoteName, &item.Content, &item.CreateTime, &item.AgreeCount)
			count += 1

			if item.Pid == 0 {
				m[item.Id] = item
				continue
			}

			if v, ok := m[item.Pid]; ok {
				*v.Replies = append(*v.Replies, item)
			} else {
				m[item.Id] = item
			}
		}
		_ = rows.Close()
		// map 无序，所以需要重新排序
		for _, v := range m {
			result = append(result, v)
		}
		// 重新按创建时间排序
		sort.Stable(result)
		return result, count
	}
	return CommentBodyList{}, 0
}

// 添加评论
func addComment(body CommentBody) (int, error) {
	if body.UserId == "" {
		return 0, errors.New("user id is required")
	}

	defaultSql := "INSERT INTO COMMENTS(PID, DOC_ID, USER_ID, USER_NAME, QUOTE_ID, QUOTE_NAME, CONTENT) VALUES (?, ?, ?, ?, ? , ?, ?)"
	if db, err := getConn(); err == nil {
		if body.Pid > 0 && !existComment(db, body.Pid) {
			return 0, errors.New(fmt.Sprintf("Comment Not Exist(ID=%d)", body.Pid))
		}
		stmt, err := db.Prepare(defaultSql)
		if err != nil {
			return 0, err
		}
		res, err := stmt.Exec(body.Pid, body.DocId, body.UserId, body.UserName, body.QuoteId, body.QuoteName, body.Content)
		if err != nil {
			return 0, err
		}
		affect, err := res.RowsAffected()
		return int(affect), err
	} else {
		return 0, err
	}
}

// 删除评论
func deleteComment(id string) (int, error) {
	defaultSql := "UPDATE COMMENTS SET DELETED = 1 WHERE DELETED = 0 AND (ID = ? OR PID = ?)"
	if db, err := getConn(); err == nil {
		return update(db, defaultSql, id, id)
	} else {
		return 0, err
	}
}

// 赞同评论
func agreeComment(id int) (int, error) {
	defaultSql := "UPDATE COMMENTS SET AGREE_COUNT = AGREE_COUNT + 1 WHERE DELETED = 0 AND ID = ?"
	if db, err := getConn(); err == nil {
		return update(db, defaultSql, id)
	} else {
		return 0, err
	}
}
